package com.smart_campus.sys.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import com.smart_campus.sys.common.ActiveUser;
import com.smart_campus.sys.common.Constant;
import com.smart_campus.sys.common.MenuTreeNode;
import com.smart_campus.sys.common.ResultObj;
import com.smart_campus.sys.domain.Loginfo;
import com.smart_campus.sys.domain.Menu;
import com.smart_campus.sys.domain.User;
import com.smart_campus.sys.service.MenuService;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @Author:Omega
 * @Date:2020/6/6 16:04
 */
//@CrossOrigin
@Controller
@RequestMapping("login")
public class LoginController {

    @Autowired
    private com.smart_campus.sys.mapper.LoginfoMapper LoginfoMapper;

    @Autowired
    private MenuService menuService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 后台用户登录
     * @param loginname
     * @param password
     * @return
     */
    @RequestMapping(value = "doSysLogin",method = RequestMethod.POST)
    @ResponseBody
    public ResultObj doSysLogin(String loginname, String password, HttpServletRequest request,String keyCode,String captcha){
        try{
            ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
            String code = opsForValue.get(keyCode);
            if(null==code){
                return new ResultObj(-1,"验证码过期");
            }else {
                if(code.equalsIgnoreCase(captcha)){
                    Subject subject= SecurityUtils.getSubject();
                    UsernamePasswordToken loginToken = new UsernamePasswordToken(loginname,password);
                    subject.login(loginToken);
                    String token = subject.getSession().getId().toString();
                    //写入登陆日志
                    ActiveUser activeUser= (ActiveUser) subject.getPrincipal();
                    User user=activeUser.getUser();
                    Loginfo loginfo = new Loginfo();
                    loginfo.setLoginname(user.getLoginname());
                    loginfo.setLoginip(request.getRemoteAddr());
                    UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
                    Browser browser = userAgent.getBrowser();
                    //浏览器信息
                    loginfo.setBrowserName(browser.getName());
                    //客户端系统名称
                    loginfo.setSystemName(System.getProperty("os.name"));
                    //客户端系统版本
                    loginfo.setSystemVersion(System.getProperty("os.version"));
                    //客户端操作系统位数

                    loginfo.setArch(System.getProperty("os.arch"));
                    //请求编码格式
                    loginfo.setEncoding(request.getCharacterEncoding());
                    //客户机所使用的网络端口号
                    loginfo.setRemoteport(request.getRemotePort());
                    //WEB服务器的IP地址
                    loginfo.setLocaladdr(request.getLocalAddr());
                    //客户机请求方式
                    loginfo.setMethod(request.getMethod());
                    loginfo.setLogintime(new Date());
                    LoginfoMapper.insert(loginfo);
                    List<String> permissions = activeUser.getPermissions();
                    Map<String,Object> map=new HashMap<>();
                    map.put("token",token);
                    map.put("permissions",permissions);
                    map.put("usertype",user.getRole());
                    map.put("username",user.getLoginname());
                    return new ResultObj(200,"登录成功",map);
                }else {
                    return new ResultObj(-1,"验证码出错");
                }
            }
        }catch (AuthenticationException e){
            e.printStackTrace();
            return new ResultObj(-1,"用户密码不正确");
        }
    }

    /**
     * 前台用户登录
     * @param loginname
     * @param password
     * @return
     */
    @RequestMapping(value = "doLogin",method = RequestMethod.POST)
    @ResponseBody
    public ResultObj doUserLogin(String loginname, String password, HttpServletRequest request, HttpSession session){
        try{
            Subject subject= SecurityUtils.getSubject();
            UsernamePasswordToken loginToken = new UsernamePasswordToken(loginname,password);
            subject.login(loginToken);
            String token = subject.getSession().getId().toString();
            //写入登陆日志
            ActiveUser activeUser= (ActiveUser) subject.getPrincipal();
            User user=activeUser.getUser();
            Loginfo loginfo = new Loginfo();
            loginfo.setLoginname(user.getLoginname());
            loginfo.setLoginip(request.getRemoteAddr());
            UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
            Browser browser = userAgent.getBrowser();
            //浏览器信息
            loginfo.setBrowserName(browser.getName());
            //客户端系统名称
            loginfo.setSystemName(System.getProperty("os.name"));
            //客户端系统版本
            loginfo.setSystemVersion(System.getProperty("os.version"));
            //客户端操作系统位数

            loginfo.setArch(System.getProperty("os.arch"));
            //请求编码格式
            loginfo.setEncoding(request.getCharacterEncoding());
            //客户机所使用的网络端口号
            loginfo.setRemoteport(request.getRemotePort());
            //WEB服务器的IP地址
            loginfo.setLocaladdr(request.getLocalAddr());
            //客户机请求方式
            loginfo.setMethod(request.getMethod());
            loginfo.setLogintime(new Date());
            LoginfoMapper.insert(loginfo);
            List<String> permissions = activeUser.getPermissions();
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            map.put("permissions",permissions);
            map.put("usertype",user.getRole());
            map.put("username",user.getLoginname());
            return new ResultObj(200,"登录成功",map);
        }catch (AuthenticationException e){
            e.printStackTrace();
            return new ResultObj(-1,"用户密码不正确");
        }
    }

    /**
     * 加载所有菜单
     * @return
     */
    @RequestMapping("loadIndexMenu")
    @ResponseBody
    public Object loadIndexMenu(){
        //得到当前登录用户
        Subject subject = SecurityUtils.getSubject();
        ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
        //得到的用户数据传入user
        User user = activeUser.getUser();
        if (user == null) {
            return null;
        }
        List<Menu> menus = null;
        HashMap<String, Object> dataMap = new HashMap<>();
        //如果是超级管理员  不同的角色给的 查出来的菜单不同，·此处全查询
        dataMap.put("available",Constant.AVAILABLE_TRUE);
        dataMap.put("type",Constant.MENU_TYPE_MENU);

        if("0".equals(user.getRole())){
            menus = menuService.queryAllMenuForList(dataMap);
        }else{
            menus = menuService.queryMenuForListUserById(dataMap,user.getUserId());
        }

        List<MenuTreeNode> treeNodes=new ArrayList<>();

        for (Menu m : menus) {
            Boolean spread=m.getSpread()==Constant.SPREAD_TRUE?true:false;
            treeNodes.add(new MenuTreeNode(m.getId(),m.getPid(),m.getTitle(),m.getHref(),m.getIcon(),spread,m.getTarget(),m.getTypecode()));
        }
        List<MenuTreeNode> nodes = MenuTreeNode.MenuTreeNodeBuilder.bulid(treeNodes, 0);
        Map<String,Object> res=new HashMap<>();
        for (MenuTreeNode n : nodes) {
            res.put(n.getTypecode(),n);
        }
        return res;
    }
    /**
     * 动态验证当前token是否登录
     * @return
     */
    @ResponseBody
    @RequestMapping("checkLogin")
    public ResultObj checkLogin(){
        Subject subject = SecurityUtils.getSubject();
        //如果验证了的话
        if (subject.isAuthenticated()){
            return ResultObj.IS_LOGIN;
        }else {
            return ResultObj.UN_LOGIN;
        }
    }

    /**
     * 验证码
     * @param response
     * @param codeKey
     * @throws IOException
     */
    @RequestMapping("captcha")
    public void captcha(HttpServletResponse response,String codeKey) throws IOException {
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(100, 38, 4, 5);
        String code = captcha.getCode();
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(codeKey,code);
        opsForValue.getOperations().expire(codeKey,60, TimeUnit.SECONDS);
        captcha.write(response.getOutputStream());
    }

}
